﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections;
using System.Collections.Generic;
using InterLinq.Types;
using Sebarf.Core.Interfaces;
using Sebarf.Diagnostics.Interfaces;
using Sebarf.Services.Interfaces;
using Sebastof.Services.Interfaces;
using Utils;

#endregion

namespace Sebastof.ProcessChains.ProcessSteps {
	/// <summary>
	/// Inverse of <see cref="DecorateCollection"/>
	/// </summary>
	public class UnDecorateCollection : ProcessStepConverter<CollectionTransporter, IEnumerable> {
		#region Public Properties

		[ServiceRequest]
		public IMetadataLocatorService MetadataLocatorRegisterService { get; private set; }

		[ServiceRequest]
		public IServiceLocatorService ServiceLocatorService { get; private set; }

		[ServiceRequest]
		public ISerializationDataHandlingStrategyService SerializationDataHandlingStrategyService {
			get { return m_dataHandlingStrategyService; }
			set { m_dataHandlingStrategyService = value; }
		}

		[ServiceRequest]
		public IObservableCollectionCreatorService ObservableCollectionCreatorService {
			get { return m_observableCollectionCreatorService; }
			set { m_observableCollectionCreatorService = value; }
		}

		[ServiceRequest]
		public IObjectTreeFlattenerService ObjectTreeHelperService {
			get { return m_objectTreeHelperService; }
			set { m_objectTreeHelperService = value; }
		}

		#endregion

		#region Public Methods

		public UnDecorateCollection(IServiceLocatorService serviceLocator) {
			MetadataLocatorRegisterService = serviceLocator.GetRegisteredService<IMetadataLocatorService>();
			Check.ArgumentNotNull(MetadataLocatorRegisterService, "MetadataContext");
			ServiceLocatorService = serviceLocator;
			m_dataHandlingStrategyService = serviceLocator.GetRegisteredService<ISerializationDataHandlingStrategyService>();
			m_observableCollectionCreatorService = serviceLocator.GetRegisteredService<IObservableCollectionCreatorService>();
			m_objectTreeHelperService = serviceLocator.GetRegisteredService<IObjectTreeFlattenerService>();
		}

		public UnDecorateCollection() {
		}

		protected override IEnumerable Convert(CollectionTransporter toProcess) {
			MetadataLocatorRegisterService.OverwriteMetadataWith(toProcess.TransferedMetadata);
			var objectToProcess = new List<ISebastofApplicationObject>();
			foreach (object o in toProcess.TransferedMetadata.GetAllObjects()) {
				var oila = o as ISebastofApplicationObject;
				if (oila != null) {
					objectToProcess.Add(oila);
				}
			}
			//foreach (var obj in toProcess.Values) {
			//	var nestedobjs = m_objectTreeHelperService.GetFlattenTree(obj);
			foreach (ISebastofApplicationObject entry in objectToProcess) {
				try {
					ISebastofApplicationObject nestedo = entry; //.ObjectValue;
					if (nestedo is SebastofApplicationObject) {
						var iObject = nestedo as SebastofApplicationObject;
						iObject.AttachedServiceLocatorService = ServiceLocatorService;
						try {
							if (toProcess.TransferedData.ContainsKey(iObject.Id)) {
								m_dataHandlingStrategyService.RestoreObjectFromTransferedData(nestedo, toProcess.TransferedData[iObject.Id]);
							}
						}
						catch {
							throw;
						}
						// replace collecions
						foreach (var item in iObject.GetValues()) {
							iObject.SetValue(item.Key,
											  m_observableCollectionCreatorService.ConvertToObservableCollection(item.Value, iObject,
																												  item.Key));
						}
					}
				}
				catch {
					throw;
				}
			}
			//}
			foreach (object obj in MetadataLocatorRegisterService.GetAllObjects()) {
				if (obj is SebastofApplicationObject) {
					// ensure attached context
					var iObject = obj as SebastofApplicationObject;
					iObject.AttachedServiceLocatorService = ServiceLocatorService;
				}
			}

			return toProcess.Values;
		}

		#endregion

		#region Private Fields

		[NonSerialized]
		private ISerializationDataHandlingStrategyService m_dataHandlingStrategyService;

		[NonSerialized]
		private IObjectTreeFlattenerService m_objectTreeHelperService;
		[NonSerialized]
		private IObservableCollectionCreatorService m_observableCollectionCreatorService;

		#endregion
	}
}